package com.base.common.taglib;

import java.util.List;
import java.util.Set;
import java.util.TreeSet;

import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;

import com.base.commons.SpringBeanHolder;
import com.base.security.SecurityUserHolder;
import com.base.security.entity.SecurityUser;
import com.base.security.service.SecurityService;

/**
 * 授权判断里面的公用方法
 * 
 * 
 */
public class GrantedELTab {
	private static Set<String> parse(String grantedRoles) {
		Set<String> parsedAuthorities = new TreeSet<String>();
		if (grantedRoles == null || grantedRoles.isEmpty()) {
			return parsedAuthorities;
		}
		String[] parsedAuthoritiesArr;
		if (grantedRoles.contains(",")) {
			parsedAuthoritiesArr = grantedRoles.split(",");
		} else {
			parsedAuthoritiesArr = new String[] { grantedRoles };
		}
		for (String auth : parsedAuthoritiesArr)
			parsedAuthorities.add(auth.trim());
		return parsedAuthorities;
	}

	/**
	 * 中心判断
	 * 
	 * @param units
	 * @return
	 */
	public static boolean unitGranted(String units) {
		Set<String> temp = parse(units);
		// 如果有本人这个字符串，优先判断
		// if (temp.contains(SecurityConst.TAGLIB_CURRENT))
		// return true;
		String unitId = SecurityUserHolder.getCurrentUnitId();
		if (temp.contains(unitId))
			return true;
		return false;
	}

	/**
	 * 部门判断
	 * 
	 * @param deps
	 * @return
	 */
	public static boolean depGranted(String deps) {
		Set<String> temp = parse(deps);
		// if (temp.contains(SecurityConst.TAGLIB_CURRENT))
		// return true;
		String depId = SecurityUserHolder.getCurrentDepartmentId();
		if (temp.contains(depId))
			return true;
		return false;
	}

	/**
	 * 人员判断
	 * 
	 * @param users
	 * @return
	 */
	public static boolean userGranted(String users) {
		Set<String> temp = parse(users);
		// if (temp.contains(SecurityConst.TAGLIB_CURRENT))
		// return true;
		String userId = SecurityUserHolder.getCurrentUserId();
		if (temp.contains(userId))
			return true;
		return false;
	}

	private static GrantedAuthority[] getUserAuthorities() {
		if (SecurityContextHolder.getContext() == null) {
			System.out
					.println("security context is empty, this seems to be a bug/misconfiguration!");
			return new GrantedAuthority[0];
		}
		Authentication currentUser = SecurityContextHolder.getContext()
				.getAuthentication();
		if (currentUser == null)
			return new GrantedAuthority[0];

		List<GrantedAuthority> authorities = (List<GrantedAuthority>) currentUser
				.getAuthorities();
		if (authorities == null)
			return new GrantedAuthority[0];

		return authorities.toArray(new GrantedAuthority[] {});
	}

	/**
	 * Method that checks if the user holds <b>any</b> of the given roles.
	 * Returns <code>true, when the first match is found, <code>false</code> if
	 * no match is found and also <code>false</code> if no roles are given
	 * 
	 * @param grantedRoles
	 *            a comma seperated list of roles
	 * @return true if any of the given roles are granted to the current user,
	 *         false otherwise
	 */
	public static boolean ifAnyGranted(final String grantedRoles) {
		Set<String> parsedAuthorities = parse(grantedRoles);
		if (parsedAuthorities.isEmpty())
			return false;
		GrantedAuthority[] authorities = getUserAuthorities();
		for (GrantedAuthority authority : authorities) {
			if (parsedAuthorities.contains(authority.getAuthority()))
				return true;
		}
		return false;
	}

	/**
	 * Method that checks if the user holds <b>all</b> of the given roles.
	 * Returns <code>true</code>, iff the user holds all roles,
	 * <code>false</code> if no roles are given or the first non-matching role
	 * is found
	 * 
	 * @param requiredRoles
	 *            a comma seperated list of roles
	 * @return true if all of the given roles are granted to the current user,
	 *         false otherwise or if no roles are specified at all.
	 */
	public static boolean ifAllGranted(final String requiredRoles) {
		// parse required roles into list
		Set<String> requiredAuthorities = parse(requiredRoles);
		if (requiredAuthorities.isEmpty())
			return false;
		// get granted roles
		GrantedAuthority[] authoritiesArray = getUserAuthorities();
		Set<String> grantedAuthorities = new TreeSet<String>();
		for (GrantedAuthority authority : authoritiesArray) {
			grantedAuthorities.add(authority.getAuthority());
		}
		// iterate over required roles,
		for (String requiredAuthority : requiredAuthorities) {
			// check if required role is inside granted roles
			// if not, return false
			if (!grantedAuthorities.contains(requiredAuthority)) {
				return false;
			}
		}
		return true;
	}

	/**
	 * Method that checks if <b>none</b> of the given roles is hold by the user.
	 * Returns <code>true</code> if no roles are given, or none of the given
	 * roles match the users roles. Returns <code>false</code> on the first
	 * matching role.
	 * 
	 * @param notGrantedRoles
	 *            a comma seperated list of roles
	 * @return true if none of the given roles is granted to the current user,
	 *         false otherwise
	 */
	public static boolean ifNotGranted(final String notGrantedRoles) {
		Set<String> parsedAuthorities = parse(notGrantedRoles);
		if (parsedAuthorities.isEmpty())
			return true;
		GrantedAuthority[] authorities = getUserAuthorities();
		for (GrantedAuthority authority : authorities) {
			if (parsedAuthorities.contains(authority.getAuthority()))
				return false;
		}
		return true;
	}

	/**
	 * 根据资源判断
	 * 
	 * @param resources
	 * @return
	 */
	public static boolean ifResourceGranted(final String resources) {
		Set<String> parsedAuthorities = parse(resources);
		if (parsedAuthorities.isEmpty())
			return false;
		SecurityService ss = SpringBeanHolder.getBean("securityService");
		SecurityUser user = SecurityUserHolder.getCurrentUser();
		for (String r : parsedAuthorities) {
			if (ss.hasPrivilegeByResourceCode(user, r))
				return true;
		}
		return false;
	}
}
